#include "MessagePoster.h"
#include <qbprotocol/include/ssCmnDefine.h>
#include <qbprotocol/include/rdProto.h>
#include <qbprotocol/include/rdMessage.h>
#include <qbprotocol/include/RequestNetWrapper.h>
#include <qbprotocol/include/SSMsgStruct.h>
#include <qbkernel/include/qb_base.h>
#include <core/sharedata/login_data.h>

#ifdef WIN32
#pragma comment(lib,"ws2_32.lib")
#else
#include <arpa/inet.h>
#endif

using namespace qb;

MessagePoster::MessagePoster(int connect_id)
	: m_connect_id(connect_id)
{

}

MessagePoster::MessagePoster(int connect_id, SSRequestMsg* req, WrapReqFunc fun)
	: m_connect_id(connect_id), m_req(req), m_reqWrapFunc(fun)
{

}

int MessagePoster::send(char* buf, int iLen, int msgType)
{
	xMsgHeadReq_t xhead;
	xhead.msgtype = htonl(msgType);

	int off = 0;
	char sndBuf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN];
	memset(sndBuf, 0x00, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);
	rdMessage::bPack((char*)&xhead, sizeof(xhead), (char*)buf, iLen, sndBuf, &off);

	return qbBase::getMessageKernel()->Send(m_connect_id, sndBuf, off);
}

int MessagePoster::send(MessageReceiver* pr)
{
	char buf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN] = "";
	memset(buf, 0, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);
	if (m_req->m_RequestID == 0)
		m_req->m_RequestID = GetRequestID();

	qb::proto::Message msg;//总的Message
	AddRegMsgHead(*m_req, msg);

	char message_type[128] = "";
	sprintf(message_type, "%d", m_req->m_FuncID);
	msg.SetType(message_type);

	if (m_reqWrapFunc)
		m_reqWrapFunc(msg, m_req);

	char message_id[128];
	//新增全局语言字段，Add by LanceZhao 2015.2.26
	msg.SetString("Language", "CHS");// TODO
	sprintf(message_id, "%ld", m_req->m_RequestID);
	msg.setMessageID(message_id);////

	int length = msg.encode(buf, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);

	xMsgHeadReq_t xhead;
	xhead.msgtype = htonl(E_FID_SERVER_QPID);

	int off = 0;
	char sndBuf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN];
	memset(sndBuf, 0, Y_RD_SERVICE_MESSAGE_BLOCK_LEN);
	rdMessage::bPack((char*)&xhead, sizeof(xhead), (char*)buf, length, sndBuf, &off);

	int sendBytes = qbBase::getMessageKernel()->Send(m_connect_id, sndBuf, off);
	if (sendBytes > 0 && pr)
	{
		RequestNotifier::instance().registReqReceiver(m_req->m_RequestID, pr);
		pr->addReqs(m_req->m_RequestID);
	}
	return sendBytes > 0 ? m_req->m_RequestID : sendBytes;
}

MessageReceiver::~MessageReceiver()
{
	for (auto iter = m_reqs.begin(); iter != m_reqs.end(); ++iter)
		RequestNotifier::instance().unRegistReqReceiver(*iter, this);

	for (auto pmi : m_pushes)
		RequestNotifier::instance().unRegistPushReceiver(pmi, nullptr);
}

void MessageReceiver::registPush(const PushMsgInfo& pmi, SSRequestMsg* req, WrapReqFunc fun)
{
	auto iter = std::find(m_pushes.begin(), m_pushes.end(), pmi);
	Q_ASSERT(iter == m_pushes.end());

	m_pushes.push_back(pmi);
	RequestNotifier::instance().registPushReceiver(pmi, this);
	if (req != nullptr)
	{
		req->m_FuncID = pmi.funcId;
		MessagePoster poster(qb::loginData::instance().ConnectID(), req, fun);
		poster.send(nullptr);
	}
}

void MessageReceiver::unRegistPush(const PushMsgInfo& pmi, qb::SSRequestMsg* req /*= nullptr*/, WrapReqFunc fun)
{
	RequestNotifier::instance().unRegistPushReceiver(pmi, nullptr);
	auto iter = std::find(m_pushes.begin(), m_pushes.end(), pmi);
	if (iter != m_pushes.end())
		m_pushes.erase(iter);

	if (req)
	{
		MessagePoster poster(qb::loginData::instance().ConnectID(), req, fun);
		poster.send(nullptr);
	}
}
